package com.internetCafes.spms.web.sys.service.impl;

import com.internetCafes.spms.common.CommonConstants;
import com.internetCafes.spms.common.utils.IdCardUtils;
import com.internetCafes.spms.core.annotation.DataFilter;
import com.internetCafes.spms.core.exception.RRException;
import com.internetCafes.spms.core.exception.RRExceptionCodeEnum;
import com.internetCafes.spms.web.certificate.entity.EmployeeInfo;
import com.internetCafes.spms.web.certificate.service.EmployeeInfoService;
import com.internetCafes.spms.web.sys.form.SysRegisterForm;
import com.internetCafes.spms.web.sys.mapper.UserInfoMapper;
import com.internetCafes.spms.web.sys.model.RoleInfo;
import com.internetCafes.spms.web.sys.model.UserInfo;
import com.internetCafes.spms.web.sys.service.RoleInfoService;
import com.internetCafes.spms.web.sys.service.RoleMenuInfoService;
import com.internetCafes.spms.web.sys.service.UserInfoService;
import com.internetCafes.spms.web.sys.service.UserRoleInfoService;
import com.internetCafes.spms.web.tenant.dao.TenantInfoMapper;
import com.internetCafes.spms.web.tenant.model.TenantDeptInfo;
import com.internetCafes.spms.web.tenant.model.TenantInfo;
import com.internetCafes.spms.web.tenant.model.TenantRoleInfo;
import com.internetCafes.spms.web.tenant.model.TenantRoleMenuInfo;
import com.internetCafes.spms.web.tenant.model.podo.TenantDeptInfoPlusDo;
import com.internetCafes.spms.web.tenant.model.podo.TenantDeptInfoPlusPo;
import com.internetCafes.spms.web.tenant.service.*;
import com.sms.common.util.hutool.core.collection.CollectionUtil;
import com.sms.common.util.hutool.core.util.ArrayUtil;
import com.sms.common.util.hutool.core.util.ObjectUtil;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


/**
 * 系统用户
 *
 * @author Sunny
 * @email rekeeper2011@hotmail.com
 * @date 2016年9月18日 上午9:46:09
 */
@Service("sysUserService")
public class UserInfoServiceImpl implements UserInfoService {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Autowired
    private UserRoleInfoService userRoleInfoService;
    @Autowired
    private TenantInfoMapper tenantInfoMapper;
    @Autowired
    @Lazy
    private TenantInfoService tenantInfoService;
    @Autowired
    private TenantDeptInfoService tenantDeptInfoService;
    @Autowired
    private EmployeeInfoService employeeInfoService;
    @Autowired
    private RoleInfoService roleInfoService;
    @Autowired
    private TenantRoleInfoService tenantRoleInfoService;
    @Autowired
    private RoleMenuInfoService roleMenuInfoService;
    @Autowired
    private TenantRoleMenuInfoService tenantRoleMenuInfoService;
    @Autowired
    private ITenantDeptInfoPlusService tenantDeptInfoPlusService;

    /**
     * 根据企业id列表查询企业下的用户信息
     * <p>
     * 此处由于项目历史关系
     * 用户的deptId其实对应的是实际企业id tenantId
     * </p>
     *
     * @param tenantIds 企业id列表
     * @return 企业用户信息
     * @author: Zheng
     */
    @Override
    public List<UserInfo> queryByTenantIds(List<Long> tenantIds) {
        Map<String, Object> params = new HashMap<>();
        params.put("deptIds", tenantIds);
        return userInfoMapper.queryList(params);
    }

    @Override
    public List<String> queryAllPerms(Long userId) {
        return userInfoMapper.queryAllPerms(userId);
    }

    @Override
    public List<Long> queryAllMenuId(Long userId) {
        return userInfoMapper.queryAllMenuId(userId);
    }

    @Override
    public UserInfo queryByUserName(String username) {
        return userInfoMapper.queryByUserName(username);
    }

    @Override
    public List<UserInfo> queryByName(String name) {
        return userInfoMapper.queryByName(name);
    }

    @Override
    public UserInfo queryByTypeAndUserName(int type, String name) {
        Map<String, Object> params = new HashMap<>();
        params.put("type", type);
        params.put("name", name);
        return userInfoMapper.queryByTypeAndUserName(params);
    }

    @Override
    public UserInfo queryObject(Long userId) {
        return userInfoMapper.queryObject(userId);
    }

    @Override
    // @DataFilter(tableAlias = "u", user = false)
    public List<UserInfo> queryList(Map<String, Object> map) {
        return userInfoMapper.queryList(map);
    }

    @Override
    @DataFilter(tableAlias = "u", user = false)
    public int queryTotal(Map<String, Object> map) {
        return userInfoMapper.queryTotal(map);
    }

    @Override
    @Transactional
    public void save(UserInfo user) {
        user.setCreateTime(new Date());
        //sha256加密
        String salt = RandomStringUtils.randomAlphanumeric(20);
        user.setPassword(new Sha256Hash(user.getPassword(), salt).toHex());
        user.setSalt(salt);
        userInfoMapper.save(user);

        //保存用户与角色关系
        userRoleInfoService.saveOrUpdate(user.getId(), user.getRoleIdList());
    }

    @Override
    @Transactional
    public void saveTenantAndDepartmentAndUser(SysRegisterForm registerForm) {
        // 密码校验
        if (StringUtils.isBlank(registerForm.getPassword())) {
            throw new RRException(RRExceptionCodeEnum.USER_PASSWORD_EMPTY);
        }

        // 企业信息判断
        TenantInfo tenantInfoPo = null;
        Map<String, Object> params;

        if (ObjectUtil.isNotNull(registerForm.getTenantId())) {
            tenantInfoPo = tenantInfoMapper.selectByPrimaryKey(registerForm.getId());
        }

        // 未提供有效企业id 根据已有条件查看企业信息
        if (ObjectUtil.isNull(tenantInfoPo)) {
            // 社会统一代码校验
            if (!IdCardUtils.isValidSocialCreditCode(registerForm.getCertificateCode())) {
                throw new RRException(RRExceptionCodeEnum.TENANT_CERTIFICATE_CODE_FORMAT_ERROR);
            }
            params = new HashMap<>();
            params.put("certificateCode", registerForm.getCertificateCode());
            tenantInfoPo = tenantInfoService.findFirst(params);
        }

        // 查看人员是否存在
        params = new HashMap<>();
        params.put("nameComplete", registerForm.getContact());
        if (ObjectUtil.isNotNull(tenantInfoPo)) {
            params.put("deptId", tenantInfoPo.getTenantId());
        } else {
            params.put("deptName", registerForm.getOrgName());
        }
        List<UserInfo> userInfoListPo = userInfoMapper.queryList(params);
        if (CollectionUtil.isNotEmpty(userInfoListPo)) {
            throw new RRException(RRExceptionCodeEnum.USER_MOBILE_USED);
        }

        TenantDeptInfo tenantDeptInfoDeptDo = new TenantDeptInfo();
        // 创建企业信息
        if (ObjectUtil.isNull(tenantInfoPo)) {
            tenantInfoPo = new TenantInfo(registerForm.getOrgName(),
                    registerForm.getCertificateCode(), registerForm.getContact(), registerForm.getMobile());
            tenantInfoPo.setStatus(CommonConstants.CommonStatus.ENABLE);
            tenantInfoMapper.insert(tenantInfoPo);
            // 创建部门
            tenantDeptInfoDeptDo = new TenantDeptInfo(tenantInfoPo.getTenantId(),
                    CommonConstants.DEFAULT_DEPARTMENT, 0L, CommonConstants.CommonStatus.ENABLE,
                    0, CommonConstants.CommonStatus.ENABLE);
            tenantDeptInfoService.save(tenantDeptInfoDeptDo);
        } else {
            TenantDeptInfoPlusDo tenantDeptInfoPlusDo = new TenantDeptInfoPlusDo();
            tenantDeptInfoPlusDo.setTenantId(tenantInfoPo.getTenantId());
            List<TenantDeptInfoPlusPo> tenantIdInfoListPo = tenantDeptInfoPlusService.deptList(tenantDeptInfoPlusDo);
            if (CollectionUtil.isEmpty(tenantIdInfoListPo)) {
                tenantDeptInfoDeptDo.setId(0L);
            } else {
                TenantDeptInfoPlusPo tenantDeptInfoPlusPo = CollectionUtil.getFirst(tenantIdInfoListPo);
                List<TenantDeptInfoPlusPo> tenantDeptInfoPlusPoList = tenantIdInfoListPo.stream()
                        .filter(po -> po.getId().equals(registerForm.getTenantDeptId()))
                        .collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(tenantDeptInfoPlusPoList)) {
                    tenantDeptInfoPlusPo = CollectionUtil.getFirst(tenantDeptInfoPlusPoList);
                }
                BeanUtils.copyProperties(tenantDeptInfoPlusPo, tenantDeptInfoDeptDo);
            }
        }

        RoleInfo roleInfo;
        if (ArrayUtil.isEmpty(registerForm.getRoleIdList())) {
            roleInfo = roleInfoService.queryObject(CommonConstants.RoleInfoType.TENANT_CONTACT);
        } else {
            roleInfo = roleInfoService.queryObject(ArrayUtil.firstNonNull(registerForm.getRoleIdList()));
        }

        TenantRoleInfo tenantRoleInfoDo = new TenantRoleInfo();
        BeanUtils.copyProperties(roleInfo, tenantRoleInfoDo);
        tenantRoleInfoDo.setTenantId(tenantInfoPo.getTenantId());
        tenantRoleInfoDo.setRoleId(roleInfo.getId());
        tenantRoleInfoDo.setCreateTime(new Date());
        tenantRoleInfoService.save(tenantRoleInfoDo);

        List<Long> menuIdList = roleMenuInfoService.queryMenuIdList(roleInfo.getId());
        if (menuIdList != null && menuIdList.size() > 0) {
            List<TenantRoleMenuInfo> tenantRoleMenuInfoBatch = new ArrayList<>();
            for (Long menuId : menuIdList) {
                tenantRoleMenuInfoBatch.add(new TenantRoleMenuInfo(tenantInfoPo.getTenantId(), roleInfo.getId(), menuId));
            }
            tenantRoleMenuInfoService.saveBatch(tenantRoleMenuInfoBatch);
        }

        EmployeeInfo employeeInfoDo = new EmployeeInfo(
                CommonConstants.EmployeeInfoType.TENANT_CONTANT, tenantInfoPo.getTenantId(),
                tenantDeptInfoDeptDo.getId(), registerForm.getNickName(), registerForm.getMobile());
        employeeInfoDo.setStatus(CommonConstants.CommonStatus.ENABLE);
        employeeInfoDo.setEmployeeFlag(CommonConstants.CommonStatus.ENABLE);
        employeeInfoService.save(employeeInfoDo);

        UserInfo userDo = new UserInfo(
                registerForm.getContact(), registerForm.getNickName(), registerForm.getPassword(), registerForm.getMobile(),
                tenantInfoPo.getTenantId(), tenantInfoPo.getTenantName(), CommonConstants.UserInfoType.TENANT_CONTANT,
                employeeInfoDo.getId());
        userDo.setNickName(registerForm.getNickName());
        userDo.setEmail(registerForm.getEmail());
        userDo.getRoleIdList().add(roleInfo.getId());
        userDo.setTenantId(tenantInfoPo.getTenantId());
        if (registerForm.isAuth()) {
            userDo.setStatus(Integer.valueOf(registerForm.getUserStatus()));
        } else {
            userDo.setStatus(Integer.valueOf(registerForm.getUserStatus()));
        }
        save(userDo);
    }

    @Override
    @Transactional
    public void update(UserInfo user) {
        UserInfo u = queryObject(user.getId());
        if (StringUtils.isBlank(user.getPassword())) {
            user.setPassword(null);
        } else {
            user.setPassword(new Sha256Hash(user.getPassword(), u.getSalt()).toHex());
        }
        userInfoMapper.update(user);

        //保存用户与角色关系
        userRoleInfoService.saveOrUpdate(user.getId(), user.getRoleIdList());
    }

    @Override
    public void justUpdate(UserInfo user) {
        userInfoMapper.update(user);
    }

    @Override
    @Transactional
    public void deleteBatch(Long[] userId) {
        userInfoMapper.deleteBatch(userId);
    }

    @Override
    public int updatePassword(Long userId, String password, String newPassword) {
        Map<String, Object> map = new HashMap<>();
        map.put("id", userId);
        map.put("password", password);
        map.put("newPassword", newPassword);
        return userInfoMapper.updatePassword(map);
    }

    @Override
    public List<UserInfo> queryByTypeAndUserId(Integer type, Long userId) {
        Map<String, Object> params = new HashMap<>();
        params.put("type", type);
        params.put("userId", userId);
        return userInfoMapper.queryByTypeAndUserId(params);
    }

    @Override
    public List<UserInfo> selectByParams(Map<String, Object> params) {
        return userInfoMapper.selectByParams(params);
    }

    @Override
    public UserInfo queryByNickName(String nickName) {
        return userInfoMapper.queryByNickName(nickName);
    }

    @Override
    public UserInfo queryByOrgNameAndUseName(Map<String, Object> params) {
        return userInfoMapper.queryByOrgNameAndUseName(params);
    }

    @Override
    public List<UserInfo> queryByOrgNameAndUseNameAndType(Map<String, Object> params) {
        return userInfoMapper.queryByOrgNameAndUseNameAndType(params);
    }

    @Override
    public UserInfo getByTenantIdAndName(Long tenantId, String name) {
        return userInfoMapper.getByTenantIdAndName(tenantId, name);
    }

}
